package org.yu.team2023.flashdays.item;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import lombok.Getter;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.network.chat.Component;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.Attribute;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
import net.minecraftforge.common.util.NonNullFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.yu.team2023.flashdays.*;
import top.theillusivec4.curios.api.SlotContext;
import top.theillusivec4.curios.api.type.capability.ICurio;
import top.theillusivec4.curios.api.type.capability.ICurioItem;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

public class TreasureCurios extends Item implements ICurioItem , ITreasureXP {
    @Getter
    private final String setKey;
    @Getter final int index;
    public TreasureCurios(Properties properties, String key, int index) {
        super(properties);
        this.setKey = key;
        this.index = index;
    }

    public static NonNullFunction<Properties, TreasureCurios> create(String key,int setIndex) {
        return (p) -> new TreasureCurios(p.stacksTo(1).fireResistant(), key,setIndex);
    }

    @Nullable
    public static TreasureData getData(ItemStack stack) {
        if (stack.hasTag() && stack.getOrCreateTag().contains("TreasureSets")) {
            return new TreasureData(stack);
        }
        return null;
    }



    public static ItemStack newInstance(Item item) {
        ItemStack stack = new ItemStack(item);
        if(item instanceof TreasureCurios curios) {
            new TreasureData(ModUtil.randomSelect(Arrays.stream(TreasureQuality.values()).toList()), curios.index).save(stack);
        }
        return stack;
    }

    public static ItemStack newInstance(Item item, TreasureQuality quality,int slotIndex) {
        ItemStack stack = new ItemStack(item);
        if(item instanceof TreasureCurios curios) {
            new TreasureData(quality,curios.index).save(stack);
        }

        return stack;
    }

    protected List<Component> getSetDesc() {
        ImmutableList.Builder<Component> list=new  ImmutableList.Builder<>();
        list.add(Component.translatable("tip." + this.setKey + ".nameDesc").withStyle(ChatFormatting.GOLD));
        if(!Screen.hasShiftDown())list.add(Component.translatable("tip.flashdays.shift_show_set"));
        else {
            list.add(Component.translatable("tip.secondEffect"));
            list.add(Component.translatable(getDescKey()));
            if(I18n.exists(getDescKeyFourth())) {
                list.add(Component.translatable("tip.fourthEffect"));
                list.add(Component.translatable(getDescKeyFourth()));
            }
        }
        return list.build();
    }

    @NotNull
    @Override
    public ICurio.DropRule getDropRule(SlotContext slotContext, DamageSource source, int lootingLevel, boolean recentlyHit, ItemStack stack) {
        return ICurioItem.super.getDropRule(slotContext, source, lootingLevel, recentlyHit, stack);
    }

    @Override
    public Multimap<Attribute, AttributeModifier> getAttributeModifiers(SlotContext slotContext, UUID uuid, ItemStack stack) {
        if (stack.hasTag() && stack.getOrCreateTag().contains("TreasureSets")) {
            return new TreasureData(stack).getAttributeModifiers();
        }
        return ICurioItem.super.getAttributeModifiers(slotContext, uuid, stack);
    }

    @Override
    public void onEquip(SlotContext slotContext, ItemStack prevStack, ItemStack stack) {
        ICurioItem.super.onEquip(slotContext, prevStack, stack);
        if (slotContext.entity() instanceof Player player) {
            player.getCapability(PlayerRPGCapabilityProvider.CAPABILITY)
                    .ifPresent(playerCuriosSetCapability -> playerCuriosSetCapability.addKey(getSetKey()));
        }
    }

    @NotNull
    @Override
    public Component getName(ItemStack stack) {
        var re = Component.translatable(getDescriptionId());
        if (!stack.hasTag() && stack.getOrCreateTag().contains("TreasureSets")) {
            re.append(Component.translatable("tip.flashdays.onlyshow"));
        }
        return re;
    }

    @Override
    public void onUnequip(SlotContext slotContext, ItemStack newStack, ItemStack stack) {
        ICurioItem.super.onUnequip(slotContext, newStack, stack);
        if (slotContext.entity() instanceof Player player) {
            player.getCapability(PlayerRPGCapabilityProvider.CAPABILITY)
                    .ifPresent(playerCuriosSetCapability -> playerCuriosSetCapability.removeKey(getSetKey()));
        }
    }


    @NotNull
    @Override
    public Rarity getRarity(ItemStack stack) {
        if (stack.hasTag() && stack.getOrCreateTag().contains("TreasureSets")) {
            return new TreasureData(stack).getQuality().getRarity();
        }
        return Rarity.COMMON;
    }

    @Override
    public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level, List<Component> list, TooltipFlag tooltipFlag) {
        if (stack.hasTag() && stack.getOrCreateTag().contains("TreasureSets")) {
            TreasureData data=new TreasureData(stack);
            list.add(Component.translatable("tip.flashdays.upgradeCount",data.getLevel()));
            list.add(Component.translatable("tip.flashdays.treasure_upgrade_xp", data.getTotalXpHas()).withStyle(ChatFormatting.GOLD,ChatFormatting.BOLD));
            list.add(data.getUpgradeProgress());
        }
        list.addAll(getSetDesc());
    }

    @Override
    public List<Component> getSlotsTooltip(List<Component> tooltips, ItemStack stack) {
        return List.of();
    }

    @Override
    public List<Component> getAttributesTooltip(List<Component> tooltips, ItemStack stack) {
        if (stack.hasTag() && stack.getOrCreateTag().contains("TreasureSets")) {
            return new TreasureData(stack).getAttributesTooltip(new ArrayList<>());
        }
        return ICurioItem.super.getAttributesTooltip(tooltips, stack);
    }

    @Override
    public boolean canEquipFromUse(SlotContext slotContext, ItemStack stack) {
        return true;
    }

    @Override
    public int getTreasureXp(ItemStack stack) {
        if (stack.hasTag() && stack.getOrCreateTag().contains("TreasureSets")) {
            return new TreasureData(stack).getTotalXpHas()*stack.getCount();
        }
        return 0;
    }
    public String getDescKey() {
        return "tip." + getSetKey() + ".desc";
    }
    public String getDescKeyFourth() {
        return getDescKey()+4;
    }

    @NotNull
    @Override
    public ICurio.DropRule getDropRule(LivingEntity livingEntity, ItemStack stack) {
        return ICurio.DropRule.ALWAYS_KEEP;
    }


}
